﻿#include "chatcontent.h"
#include <QCryptographicHash>
#include <QPainter>
#include <QPixmapCache>
#include <QStringBuilder>
#include "chatitemwidget.h"
#include "emotionresource.h"

ChatPlainText::ChatPlainText(const QString &text) : text(text)
{
}

QVariant ChatPlainText::data(int role) const
{
    if(role == Qt::DisplayRole)
        return text;
    else if (role == Qt::TextAlignmentRole)
        return Qt::AlignCenter;    
    else if (role == Qt::FontRole)
    {
        QFont font;
        font.setPixelSize(10);
        return font;
    }
    return QVariant();
}

ChatDirection::ChatDirection(const bool from, const QPixmap &icon, const QVariant &display, const QString &extra) : from(from), icon(icon), display(display), extraText(extra)
{
}

QVariant ChatDirection::data(int role) const
{
    if(role == Qt::DisplayRole)
        return display;
    else if (role == Qt::DecorationRole)
        return icon;
    else if (role == Qt::UserRole)
        return from;
    else if (role == Qt::UserRole + 1)
        return extraText;
    return QVariant();
}

const QString ChatImage::brokenImage = QLatin1String(":/gui/picture_error.png");
const QString ChatImage::loadingImageFormat = QLatin1String(":/gui/picture_loading_%1.png");

static inline QString keyForUrl(const QString &url)
{
    return QLatin1String("url_pixmap_") % url;
}

ChatImage::ChatImage(const bool from, const QPixmap &icon, const QUrl &url, bool &requestDownload, const QString &extra) : ChatDirection(from, icon, QVariant(), extra),
    url(url.toString(QUrl::StripTrailingSlash | QUrl::NormalizePathSegments))
{
    if(url.scheme() == QLatin1String("qrc"))
        this->url = this->url.mid(3);
    if(url.scheme().startsWith(QLatin1String("http"))) {
        auto key = keyForUrl(this->url);
        if(auto cached = QPixmapCache::find(key))
            original = *cached;
        else
        {
            //下载
            display = QPixmap(loadingImageFormat.arg(0));
            requestDownload = true;
            return;
        }
    }
    else
        original.load(this->url);
    handleOriginal(true);
    requestDownload = false;
}

ChatImage::ChatImage(const QPixmap &icon, const QPixmap &pix) : ChatDirection(false, icon), original(pix)
{
    handleOriginal(true);
}

QVariant ChatImage::data(int role) const
{
    if(role == Qt::EditRole)
        return original;
    else
        return ChatDirection::data(role);
}

QString ChatImage::getUrl() const
{
    return url;
}

void ChatImage::downloadFinished(const QPixmap &pixmap, const QByteArray &md5)
{
    original = pixmap;
    this->md5 = md5;
    handleOriginal(false);
}

void ChatImage::downloadError()
{
    handleOriginal(false);
}

void ChatImage::downloadProgress(int progress)
{
    if(original.isNull())
        display = QPixmap(loadingImageFormat.arg(progress));
}

void ChatImage::handleOriginal(bool createMd5)
{
    if(!original.isNull())
    {
        if(createMd5)
            this->createMd5();
        createShow();
    }
    else
        display = QPixmap(brokenImage);
}

void ChatImage::createMd5()
{
    QImage image = original.toImage();
    if(!image.isNull())
    {
        QCryptographicHash hash(QCryptographicHash::Md5);
        hash.addData(reinterpret_cast<const char*>(image.constBits()) , image.sizeInBytes());
        md5 = hash.result().toHex();
    }
}

static const QSize thumbSize(60, 44);

void ChatImage::createShow()
{
    auto scalesSize = original.size().scaled(thumbSize, Qt::KeepAspectRatioByExpanding);
    if(scalesSize.height() >= original.height())
    {
        //不用scale
        display = original;
    }
    else if(md5.isEmpty())
        display = original.scaled(thumbSize, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
    else
    {
        auto key = QLatin1String("scale_pixmap_") % md5;
        if(auto scaled = QPixmapCache::find(key))
        {
            display = *scaled;
        }
        else
        {
            auto show = original.scaled(thumbSize, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
            QPixmapCache::insert(key, show);
            display = show;
        }
    }
}
